import * as fs from 'node:fs/promises';
import * as vscode from 'vscode';
import { fetchDocDetail } from '../api/fetchDocDetail';
import { Memory } from '../memory';
import { TornaDocDetail } from '../types/type';
import { OpenApiDoc } from './openApi';
import { genApiTsfileByDocDetail } from './genApiTsFile';
import { refreshApi } from './refreshApi';
import { fetchApiList } from './fetchApiList';

const webviewPanels = new Map<string, vscode.WebviewPanel>();

export async function viewApi(arg0: any) {
  const docItem = await OpenApiDoc.getDocItemFormAny(arg0);
  if (!docItem) { return; }
  let panel = webviewPanels.get(docItem.id);
  if (panel) {
    panel.reveal();
  } else {
    const panel = vscode.window.createWebviewPanel(
      'api_doc_viewer',
      docItem.name,
      vscode.ViewColumn.One,
      { enableScripts: true }
    );
    ApiDocViewerSerializer.get().init(panel);
    fetchDocDetail(
      docItem.visitor.url + '/doc/view/detail',
      { authorization: docItem.visitor.token },
      { id: docItem.id }
    ).then((detail) => {
      ApiDocViewerSerializer.get().deserializeWebviewPanel(panel, { detail, visitor: docItem.visitor });
    }).catch(e => {
      console.error(e);
    });
  }
}

export interface DocViewerState {
  detail: TornaDocDetail;
  visitor: Memory.IUser;
}
export class ApiDocViewerSerializer implements vscode.WebviewPanelSerializer<DocViewerState> {
  static _inst: ApiDocViewerSerializer;

  static get(): ApiDocViewerSerializer {
    this._inst = this._inst || new ApiDocViewerSerializer();
    return this._inst;
  }

  protected constructor() { }

  init(panel: vscode.WebviewPanel) {
    if (!panel.iconPath) {
      panel.iconPath = {
        light: vscode.Uri.joinPath(Memory.context().extensionUri, 'resources', 'light', 'ic_tav_api_explorer.png'),
        dark: vscode.Uri.joinPath(Memory.context().extensionUri, 'resources', 'dark', 'ic_tav_api_explorer.png')
      };
    }
  }
  genTsFile(state: DocViewerState) {
    genApiTsfileByDocDetail(state).then((result) => {
      const uri = vscode.Uri.file(result?.filePath!);
      return vscode.commands.executeCommand('vscode.open', uri);
    }).then(e => {
      vscode.window.showInformationMessage('已生成');
    }).catch((e) => {
      console.error(e);
    });
  }

  refresh(panel: vscode.WebviewPanel, state: DocViewerState) {
    const diskPath = vscode.Uri.joinPath(Memory.context().extensionUri, 'resources', 'doc_viewer.html');
    fs.readFile(diskPath.fsPath)
      .then(v => v.toString())
      .then((v) => {
        return v.replace('$_DOC_DATA', JSON.stringify(state));
      }).then((html) => {
        panel.webview.html = html;
      }).catch(e => {
        console.error(e);
      });
  }

  async deserializeWebviewPanel(panel: vscode.WebviewPanel, state: DocViewerState) {
    this.init(panel);
    const { detail } = state;
    webviewPanels.set(detail.id, panel);
    this.refresh(panel, state);
    panel.onDidDispose(() => webviewPanels.delete(detail.id));
    panel.webview.onDidReceiveMessage(message => {
      switch (message.type) {
        case 'gen':
          this.genTsFile(state);
          break;
        case 'refresh':
          console.log('[tav]refreshing...');
          fetchDocDetail(
            state.visitor.url + '/doc/view/detail',
            { authorization: state.visitor.token },
            { id: state.detail.id }
          ).then(detail => {
            this.refresh(panel, { detail, visitor: state.visitor });
          }).finally(() => {
            console.log('[tav]refresh done.');
          });
          break;
      }
    });
  }
}